import VectorSource from 'ol/source/Vector'
import Feature from 'ol/Feature'
import LineString from 'ol/geom/LineString'
import Point from 'ol/geom/Point'
import { Style, Icon, Stroke } from 'ol/style'
import { fromLonLat } from 'ol/proj'

/**
 * TextureFlow 路径流动纹理动画工具
 * 支持单个图片流动和图片队列平铺流动两种模式
 * - tile=false: 单个图片沿路径流动
 * - tile=true: 多个图片队列沿路径整体流动，可设置图片间隔gap
 *
 * 主要原理：
 * 1. 先绘制主路径线（可自定义颜色和宽度）
 * 2. 沿路径每隔(step+gap)米，绘制一个图片，所有图片整体前进，形成流动动画
 * 3. 每个图片的朝向用当前位置往前1米的切线方向，保证指向路径切线
 * 4. 动画由requestAnimationFrame驱动，speed控制流动速度
 */
export interface TextureFlowOptions {
  textureImg: string // 纹理图片路径
  speed?: number // 动画速度，越大越快
  scale?: number // 图片缩放
  opacity?: number // 图片透明度
  lineColor?: string // 路径主线颜色
  lineWidth?: number // 路径主线宽度
  tile?: boolean // 是否平铺（true=多图片队列，false=单图，默认false）
  gap?: number // 平铺时图片之间的间隙（单位：米，默认图片宽度）
}

export class TextureFlow {
  private vectorSource: VectorSource
  private animationFrameId: number | null = null
  private textureFeature: Feature | null = null // 单图流动时用
  private textureFeatures: Feature[] = [] // 平铺时用
  private pathCoords: number[][] = []
  private options: Required<TextureFlowOptions>
  private isPlaying = false

  /**
   * 构造函数
   * @param vectorSource OpenLayers的VectorSource实例
   * @param geojson 路径geojson对象
   * @param options 配置项，详见TextureFlowOptions
   */
  constructor(vectorSource: VectorSource, geojson: any, options: TextureFlowOptions) {
    this.vectorSource = vectorSource
    this.options = {
      textureImg: options.textureImg,
      speed: options.speed ?? 0.00012,
      scale: options.scale ?? 0.5,
      opacity: options.opacity ?? 1,
      lineColor: options.lineColor ?? 'rgba(0,234,255,0.5)',
      lineWidth: options.lineWidth ?? 10,
      tile: options.tile ?? false,
      gap: options.gap ?? 4500 // 稍后用图片宽度兜底
    }
    this.initPath(geojson)
  }

  /**
   * 初始化路径和主线、图片特征
   */
  private initPath(geojson: any) {
    if (!geojson?.features?.length) return
    this.pathCoords = geojson.features[0].geometry.coordinates
    this.vectorSource.clear()
    // 路径主线
    const mainLine = new Feature({ geometry: new LineString(this.pathCoords.map((c: number[]) => fromLonLat(c))) })
    mainLine.setStyle(new Style({
      stroke: new Stroke({
        color: this.options.lineColor,
        width: this.options.lineWidth,
        lineCap: 'round',
        lineJoin: 'round'
      })
    }))
    this.vectorSource.addFeature(mainLine)
    // 纹理图片特征
    if (this.options.tile) {
      // 平铺时，创建多个Feature（最多50个，实际用多少由路径长度和间隔决定）
      this.textureFeatures = []
      for (let i = 0; i < 50; i++) {
        const f = new Feature()
        this.vectorSource.addFeature(f)
        this.textureFeatures.push(f)
      }
    } else {
      // 单图流动
      this.textureFeature = new Feature()
      this.vectorSource.addFeature(this.textureFeature)
    }
  }

  /**
   * 动画帧更新函数
   * - tile=false: 单图流动，始终只有一个图片在路径上流动
   * - tile=true: 多图平铺，队列整体流动，图片间隔gap
   */
  private updateTextureAnimation = () => {
    // 如果路径点数小于2，直接返回，不进行动画。
    if (this.pathCoords.length < 2) return
    const line = new LineString(this.pathCoords.map((c: number[]) => fromLonLat(c)))
    // 计算整条路径的总长度
    const totalLength = line.getLength()
    const now = Date.now()
    // 计算动画的速度
    const t = ((now * this.options.speed) % 1)
    const frac = t
    // 平铺模式
    if (this.options.tile) {
      // 平铺队列流动
      // 先加载图片，获取宽度
      const img = new window.Image()
      img.src = this.options.textureImg
      img.onload = () => {
        const step = img.width * this.options.scale // 图片宽度（米）
        const gap = this.options.gap && this.options.gap > 0 ? this.options.gap : step
        const arrowCount = Math.floor(totalLength / (step + gap)) + 2
        // 动态调整feature数量，刚好铺满路径
        if (this.textureFeatures.length < arrowCount) {
          for (let i = this.textureFeatures.length; i < arrowCount; i++) {
            const f = new Feature()
            this.vectorSource.addFeature(f)
            this.textureFeatures.push(f)
          }
        } else if (this.textureFeatures.length > arrowCount) {
          for (let i = this.textureFeatures.length - 1; i >= arrowCount; i--) {
            this.vectorSource.removeFeature(this.textureFeatures[i])
            this.textureFeatures.pop()
          }
        }
        for (let i = 0; i < this.textureFeatures.length; i++) {
          if (i >= arrowCount) {
            this.textureFeatures[i].setGeometry(undefined)
            continue
          }
          // 每个图片的锚点 = (t * totalLength + i * (step + gap)) % totalLength
          let current = (t * totalLength + i * (step + gap)) % totalLength
          // 计算该feature在路径上的位置0~1
          const fraction = current / totalLength
          // 根据点在线上的位置比例，0~1，1是结束，计算出位置经纬度
          const coord = line.getCoordinateAt(fraction)
          // 方向用1米微步长，保证箭头指向路径切线
          // 计算朝向
          // 计算下一个位置的坐标
          const delta = 1
          const nextDist = Math.min(current + delta, totalLength)
          const nextFraction = nextDist / totalLength
          const nextCoord = line.getCoordinateAt(nextFraction)
          let rotation = 0
          if (nextCoord) {
            // 根据两个坐标计算朝向，弧度制
            rotation = Math.atan2(nextCoord[1] - coord[1], nextCoord[0] - coord[0])
          }
          this.textureFeatures[i].setGeometry(new Point(coord))
          // 设置图标偏移rotation
          this.textureFeatures[i].setStyle(new Style({
            image: new Icon({
              src: this.options.textureImg,
              scale: this.options.scale,
              rotation: -rotation,
              anchor: [0.5, 0.5],
              opacity: this.options.opacity
            })
          }))
        }
        if (this.isPlaying) {
          this.animationFrameId = requestAnimationFrame(this.updateTextureAnimation)
        }
      }
    } else {
      // 单图流动
      // 根据点在线上的位置比例，0~1，1是结束，计算出位置经纬度
      const coord = line.getCoordinateAt(frac)
      // 方向用1米微步长
      const delta = 1
      const nextDist = Math.min(frac * totalLength + delta, totalLength)
      const nextFraction = nextDist / totalLength
      const nextCoord = line.getCoordinateAt(nextFraction)
      let rotation = 0
      if (nextCoord) {
        rotation = Math.atan2(nextCoord[1] - coord[1], nextCoord[0] - coord[0])
      }
      this.textureFeature!.setGeometry(new Point(coord))
      this.textureFeature!.setStyle(new Style({
        image: new Icon({
          src: this.options.textureImg,
          scale: this.options.scale,
          rotation: -rotation,
          anchor: [0.5, 0.5],
          opacity: this.options.opacity
        })
      }))
      if (this.isPlaying) {
        this.animationFrameId = requestAnimationFrame(this.updateTextureAnimation)
      }
    }
    if (this.isPlaying) {
      // 平铺模式下，动画帧已在img.onload里递归
    }
  }

  /**
   * 启动动画
   */
  public start() {
    this.isPlaying = true
    this.animationFrameId = requestAnimationFrame(this.updateTextureAnimation)
  }

  /**
   * 停止动画
   */
  public stop() {
    this.isPlaying = false
    if (this.animationFrameId) {
      cancelAnimationFrame(this.animationFrameId)
      this.animationFrameId = null
    }
  }

  /**
   * 销毁，清理所有特征
   */
  public destroy() {
    this.stop()
    this.vectorSource.clear()
  }
} 